!> 文件系统
module fffc_filesystem

    use fffc_string, only: to_string
    implicit none

    private
    public :: is_windows, mkdir, rmdir, exists, countlines, unix_path, &
              dirname, basename, operator(.join.), read_whole_file

    interface
        module function is_windows()
            logical :: is_windows
        end function is_windows
        module subroutine mkdir(path)
            character(len=*), intent(in) :: path
        end subroutine mkdir
        module subroutine rmdir(path)
            character(len=*), intent(in) :: path
        end subroutine rmdir
        module function exists(file)
            character(len=*), intent(in) :: file
            logical :: exists
        end function exists
        integer module function countlines(file)
            character(len=*), intent(in) :: file
        end function countlines
        pure module function unix_path(path)
            character(len=*), intent(in) :: path
            character(len=len(path)) :: unix_path
        end function unix_path
        pure module function dirname(path) result(dir)
            character(len=*), intent(in) :: path
            character(len=:), allocatable :: dir
        end function dirname
        pure module function basename(path) result(base)
            character(len=*), intent(in) :: path
            character(len=:), allocatable :: base
        end function basename
    end interface

    interface operator(.join.)
        module function join(path, name)
            character(len=*), intent(in) :: path
            character(len=*), intent(in) :: name
            character(len=len(path) + len(name) + 1) :: join
        end function join
    end interface

contains

    !> read the file as a string
    function read_whole_file(file) result(string)
        character(*), intent(in) :: file  !! file name to read
        character(:), allocatable :: string  !! file content
        integer :: iunit, len, stat, i

        open (newunit=iunit, file=file, status='old', action='read')
        inquire (iunit, size=len)
        allocate (character(len=len) :: string)

        do i = 1, len - 1
            read (iunit, '(a1)', advance='no', iostat=stat) string(i:i)
            if (is_iostat_eor(stat)) string(i:i) = char(10)  !! line feed
        end do
        string(len:len) = char(0)  !! null character

        close (iunit)

    end function read_whole_file

end module fffc_filesystem
